﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ListNetRanker
{
    public class Normalizer
    {
        //Save the max and min value for each feature
        public List<Range> maxminList = new List<Range>();


        private Normalizer() { }

        public Normalizer(List<Range> mm)
        {
            maxminList = mm;
        }

        //get all features value range from all sample
        public static Normalizer CreateNormalizer(DataReader reader)
        {
            Normalizer normalizer = new Normalizer();

            reader.reset();
            Sample smaple = reader.getNextSample();

            if (smaple == null)
                return null;

            int featureSize = smaple.documents[0].features.Count;
            for (int i = 0; i < featureSize; i++)
            {
                normalizer.maxminList.Add(new Range(0.0, Double.MaxValue));
            }

            do
            {
                List<Document> docs = smaple.documents;
                foreach (Document doc in docs)
                {
                    for (int i = 0; i < featureSize; i++)
                    {
                        double val = doc.features[i];

                        if (val > normalizer.maxminList[i].getMax())
                        {
                            normalizer.maxminList[i].setMax(val);
                        }

                        if (val < normalizer.maxminList[i].getMin())
                        {
                            normalizer.maxminList[i].setMin(val);
                        }
                    }
                }
            } while ((smaple = reader.getNextSample()) != null);

            return normalizer;
        }

        //create a new document and normalize it
        public Document normalize(Document doc)
        {

            int featureSize = this.maxminList.Count;
            List<Double> oldfeatures = doc.features;
            List<Double> features = new List<Double>(featureSize);

            for (int i = 0; i < featureSize; i++)
            {
                double max = maxminList[i].getMax();
                double min = maxminList[i].getMin();

                if (max == min)
                    features.Add(0.0);
                else
                    features.Add(((double)(oldfeatures[i] - min)) / (max - min));
            }

            return new Document(doc.qid, doc.relevance, features);
        }

        //Normalize entire sample
        public Sample normalize(Sample sample)
        {
            Sample res = new Sample(sample.qid);

            List<Document> docs = sample.documents;
            //for (Document doc : docs)
            foreach (Document doc in docs)
            {
                res.add(normalize(doc));
            }

            return res;
        }
    }
}
